﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Geodatabase;
using System.Collections;
using System.Windows.Forms;
using ESRI.ArcGIS.Geometry;
using PlanningGIS.Framework.Controls;
using System.IO;
using PlanningGIS.ArcGIS;
using PlanningGIS.Win.Controls;
using PlanningGIS.Framework;
using PlanningGIS.Util.Collections;
using PlanningGIS.Util.Convertor;
using PlanningGIS.Framework.Rule;
using PlanningGIS.Engine.Controls;
using PlanningGIS.Util.Log;

namespace PlanningGIS.DataConvert.model
{
    /// <summary>
    /// 作用：DLG数据导入构造类（依据代码对应关系进行构造）
    /// </summary>
    public class DlgDataImportConstruct : DataConstruct
    {
        /// <summary>
        /// 该事件告诉调用的类，已经构造完毕
        /// </summary>
        private EventHandler ConstructTargetFeatclsOver;  

        /// <summary>
        /// 数据源依据的字段名
        /// </summary>
        public string SourceFieldName { get; set; }

        /// <summary>
        /// Dlg建库方案
        /// </summary>
        private DataImportRule dataImportRule;

        /// <summary>
        /// 创建库体用
        /// </summary>
        protected DataImportRuleBase dataImportRuleBase;    

        /// <summary>
        /// Dlg建库方案
        /// </summary>
        public DataImportRule DataImportRule
        {
            get { return dataImportRule; }
            set 
            { 
                dataImportRule = value;
                dataImportRuleBase = value as DataImportRuleBase;
                if (dataImportRule != null && !string.IsNullOrWhiteSpace(dataImportRule.SourceFieldName)) SourceFieldName = dataImportRule.SourceFieldName;
            }
        }

        /// <summary>
        /// 点要素的代码对应关系:
        /// 记录数据源与目标数据代码的对应关系，分点、线、面、注记来存储是因为不同几何类型有可能源数据的代码一样，所以要分开存储
        /// </summary>
        public Hashtable FcodeRelationPt { get; protected set; }

        /// <summary>
        /// 线要素的代码对应关系
        /// </summary>
        public Hashtable FcodeRelationLn { get; protected set; }

        /// <summary>
        /// 面要素的代码对应关系
        /// </summary>
        public Hashtable FcodeRelationPy{ get; protected set; }

        /// <summary>
        /// 注记要素的代码对应关系（有则按对应关系入库，无则全部入库）
        /// </summary>
        public Hashtable FcodeRelationAnno { get; protected set; }

        /// <summary>
        /// 空间参考
        /// </summary>
        public ISpatialReference SpatialRef { get; set; }

        /// <summary>
        /// 构造对应关系（代码之间的关系、字段之间的关系、字段默认值以及剔除掉不符合要求的数据源）
        /// </summary>
        /// <returns></returns>
        public bool Operate()
        {
            if (string.IsNullOrWhiteSpace(SourceFieldName)) return false;
            if (FeatClsListSource == null || FeatClsListSource.Count == 0) return false;
            if (!ConstructFcodeRelation()) return false;
            LogHelper.WriteLog("开始构造数据源与目标数据的对应关系...");
            //如果外界未传递，则自己构造目标要素类列表
            if (FeatClsListTarget == null || FeatClsListTarget.Count == 0)
            {
                if (IsCreateTargetFeatCls)
                {
                    if (!CreateTargetFeatClasses()) return false;
                }
                else
                {
                    if (!ConstructTargetFeatClasses()) return false;
                }
            }

            LogHelper.WriteDoneLog("获取目标要素类集合成功。\n");

            DlgDataConverts = new List<DlgDataConvert>();

            Hashtable fieldRelation;
            Hashtable fieldDefaultValue;
            DlgTargetFeatureClass dlgTargetFeatureClass = null;
            IFeatureClass pTargetFeatCls;

            LogHelper.WriteLog("开始构造数据源与目标数据的对应关系...");

            SetProcessBarMax(FeatClsListTarget.Count);

            List<IFeatureClass> pFeatClsLstTemp = new List<IFeatureClass>();

            //遍历数据源，看是否有找不到入库依据字段的，给出提示（因为要移除，所以需要倒着遍历）
            //不能删！可能用户不小心把依据字段输错了，如果删了，改好依据字段后还需要重新选择数据源，忒麻烦了
            for (int i = FeatClsListSource.Count - 1; i >= 0; i--)
            {
                IFeatureClass featCls = FeatClsListSource[i];
                if (featCls.FeatureType == esriFeatureType.esriFTAnnotation || featCls.FeatureType == esriFeatureType.esriFTCoverageAnnotation)
                {
                    if (FcodeRelationAnno.Count == 0)
                    {
                        pFeatClsLstTemp.Add(FeatClsListSource[i]);
                        continue;
                    }
                }
                if (featCls.FindField(SourceFieldName) == -1)
                {
                    LogHelper.WriteErrLog("数据源[" + featCls.AliasName + "]未找到入库依据字段[" + SourceFieldName + "].");
                    //pFeatCLsLstSource.Remove(pFeatCls);
                }
                else
                {
                    pFeatClsLstTemp.Add(FeatClsListSource[i]);
                }
            }

            if (pFeatClsLstTemp.Count == 0)
            {
                LogHelper.WriteErrLog("所有数据源中均找不到入库依据字段[" + SourceFieldName + "]，入库操作无法完成！");
                return false;
            }

            //循环目标数据
            for (int i = 0; i < FeatClsListTarget.Count; i++)
            {
                pTargetFeatCls = FeatClsListTarget[i];
                LogHelper.WriteLog("正在构建目标数据[" + pTargetFeatCls.AliasName + "]与数据源的对应关系...");
                SetProcessBarCurrent(i + 1);
                string dsname =(pTargetFeatCls as IDataset).Name;
                //dlgTargetFeatureClass = ListHelper.GetEnumeratorItem(dataImportRule.dlgTargetFeatureClasses, "FeatureClassAliasName", pTargetFeatCls.AliasName);
                dlgTargetFeatureClass = dlgTargetFeatureClass = dataImportRule.dlgTargetFeatureClasses.FirstOrDefault(t => t.FeatureClassName.Equals(dsname, StringComparison.CurrentCultureIgnoreCase)
                    || t.FeatureClassName.ToLower().Contains(dsname.ToLower())
                    || dsname.ToLower().Contains(t.FeatureClassName.ToLower()));
                if (dlgTargetFeatureClass == null)
                {
                    LogHelper.WriteErrLog("建库方案中未找到别名为[" + pTargetFeatCls.AliasName + "]的项，请核查目标数据！");
                    continue;
                }
                if ((dlgTargetFeatureClass.featureCodes == null || dlgTargetFeatureClass.featureCodes.Count == 0) && dlgTargetFeatureClass.GeometryType != "注记")
                {
                    LogHelper.WriteErrLog("目标数据[" + dlgTargetFeatureClass.FeatureClassAliasName + "]的代码列表为空，请检查。");
                    continue;
                }
                fieldRelation = GetFieldRelation(dlgTargetFeatureClass.attrFields);
                fieldDefaultValue = GetDefaultValue(dlgTargetFeatureClass);
                //循环数据源
                for (int j = 0; j < pFeatClsLstTemp.Count; j++)
                {
                    ConstructDataImportKey(pTargetFeatCls, pFeatClsLstTemp[j], dlgTargetFeatureClass, fieldRelation, fieldDefaultValue, DlgDataConverts);
                }
                Application.DoEvents();
                //if (stopAnyway) return false;
            }
           
            pFeatClsLstTemp = null; //将临时的集合清空
            if (DlgDataConverts != null && DlgDataConverts.Count > 0)
            {
                LogHelper.WriteDoneLog("数据源与目标数据的对应关系构造完毕。\n");
                return true;
            }
            else
            {
                LogHelper.WriteErrLog("数据源中无建库方案文件所配置的相关代码。构造数据源与目标数据的对应关系失败！\n");
                return false;
            }
        }

        /// <summary>
        /// 构造目标要素类，之所以该函数独立来写，是因为更新模块的需要，
        /// 要求先知道要更新的目标要素类，再进行源与目标的匹配
        /// </summary>
        public bool ConstructTargetFeatClasses()
        {
            try
            {
                if (dataImportRule == null)
                {
                    LogHelper.WriteErrLog("请选择建库方案！");
                    return false;
                }
                //stopAnyway = false;

                if (TargetWs == null)
                    TargetWs = DataConvertUtility.GetWorkSpaceByObject(dataImportRule, false);
                if (TargetWs == null)
                {
                    LogHelper.WriteErrLog("目标工作区无法打开，请检查参数设置！");
                    return false;
                }
                IFeatureDataset pTargetFeatDs = null; //判断注册版本用
                IFeatureClass pTargetFeatCls = null;
                IFeatureWorkspace pTargetFeatWs = TargetWs as IFeatureWorkspace;

                if (dataImportRule.DatasetName != "")
                {
                    pTargetFeatDs = GetTargetFeatDataset(pTargetFeatWs, dataImportRule.DatasetName);
                    if (pTargetFeatDs == null)
                    {
                       LogHelper.WriteErrLog("目标数据集:[" + dataImportRule.DatasetName + "]不存在，请检查！");
                        return false;
                    }
                }
                if (dataImportRule.dlgTargetFeatureClasses.Count == 0)
                {
                    LogHelper.WriteErrLog("建库方案中目标要素类列表为空，请检查！");
                    return false;
                }
                IFeatureClassContainer pFeatClsContainer = pTargetFeatDs as IFeatureClassContainer;
                string pFeatClsname = dataImportRule.dlgTargetFeatureClasses[0].FeatureClassName + dataImportRule.Affix;

                //modified by sheng at 2013-07-20 直接从工作空间获得
                IFeatureClass pTempFeatCls = pTargetFeatWs.OpenFeatureClass(pFeatClsname);// GetFeatCls(pFeatClsContainer, pFeatClsname);
                
                if (pTempFeatCls == null)
                {
                    
                    {
                       LogHelper.WriteErrLog("目标要素类:[" + pFeatClsname + "]不存在，请检查后缀名！");
                    }
                    return false;
                }

                //获得子版本的工作区和数据集(在构造目标要素类的时候，如果是ＳＤＥ数据需要判断是否目标数据集已被注册)
                if (TargetWs != null && pTargetFeatDs != null && TargetWs.Type == esriWorkspaceType.esriRemoteDatabaseWorkspace)
                {

                    //首先如果入的库体是SDE的话，则需要判断是否注册
                    bool IsRegistered;
                    bool IsMovingEditsToBase;

                    IVersionedObject3 versionObj = pTargetFeatDs as IVersionedObject3;
                    versionObj.GetVersionRegistrationInfo(out IsRegistered, out IsMovingEditsToBase);
                    if (!IsRegistered)
                    {
                        if (MsgHelper.ShowYesNoCancelQueryMsgbox("目标数据集未注册版本，注册版本请点击“是”，不需要注册请点击“否”。") == DialogResult.OK)
                        {
                            try
                            {
                                LogHelper.WriteLog("开始对数据进行注册...");
                                versionObj.RegisterAsVersioned3(false);
                                LogHelper.WriteDoneLog("数据注册完毕。\n");
                            }
                            catch (Exception e)
                            {
                               LogHelper.WriteErrLog("数据注册失败！" + e.Message + "\n");
                            }
                        }
                    }
                }

                //目标的要素类序列
                FeatClsListTarget = new List<IFeatureClass>();
                DlgTargetFeatureClass dlgTargetFeatureClass = null;

                //循环目标
                for (int i = 0; i < dataImportRule.dlgTargetFeatureClasses.Count; i++)
                {
                    dlgTargetFeatureClass = dataImportRule.dlgTargetFeatureClasses[i];

                    pTargetFeatCls = pTargetFeatWs.OpenFeatureClass(dlgTargetFeatureClass.FeatureClassName + dataImportRule.Affix);// GetFeatCls(pFeatClsContainer,dlgTargetFeatureClass.FeatureClassName + dataImportRule.Affix);

                    //目标数据不存在，需要写日志
                    if (pTargetFeatCls == null)
                    {
                       LogHelper.WriteErrLog("目标要素类:[" + dlgTargetFeatureClass.FeatureClassName +
                                         dataImportRule.Affix + "]不存在，请检查！");
                        continue;
                    }
                    else
                    {
                        FeatClsListTarget.Add(pTargetFeatCls);
                    }
                }

                //？何为
                if (ConstructTargetFeatclsOver != null)//构造完目标要素类后要提示外界调用的类
                {
                    ConstructTargetFeatclsOver.Invoke(null, null);
                }

                LogHelper.WriteDoneLog("构造目标要素类成功。");

                return true;

            }
            catch (Exception e)
            {
               LogHelper.WriteErrLog("构造目标要素类失败！" + e.Message);
                return false;
            }
        }

        /// <summary>
        /// 根据建库方案，创建要素类
        /// </summary>
        /// <returns></returns>
        public bool CreateTargetFeatClasses()
        {
            try
            {
                if (dataImportRuleBase == null)
                {
                    LogHelper.WriteErrLog("请选择正确的建库方案！");
                    return false;
                }
                if (TargetWs == null)
                    TargetWs = DataConvertUtility.GetWorkSpaceByObject(DataImportRule, true);
                if (TargetWs == null) return false;
                //stopAnyway = false;
                IFeatureDataset pTargetFeatDs = null; //判断注册版本用
                IFeatureClass pTargetFeatCls = null;
                ISpatialReference pSr = null;
                IFeatureWorkspace pTargetFeatWs = TargetWs as IFeatureWorkspace;

                if (!string.IsNullOrWhiteSpace(DataImportRule.DatasetName))
                {
                    pTargetFeatDs = CreateFeatureDataset(TargetWs, dataImportRuleBase.DatasetName + dataImportRuleBase.Affix);
                    if (pTargetFeatDs == null)
                    {
                        LogHelper.WriteErrLog("目标数据集:[" + DataImportRule.DatasetName + "]不存在，也无法成功创建，无法入库！");
                        return false;
                    }
                    pSr = (pTargetFeatDs as IGeoDataset).SpatialReference;
                }
                else
                {
                    pSr = GetSR();
                }
                List<DlgTargetFeatureClassBase> dlgTargetFeatureClassBases = new List<DlgTargetFeatureClassBase>();
                if (dataImportRule is DataImportRule)
                {
                    foreach (DlgTargetFeatureClass dlgTargetFeatureClass in (dataImportRuleBase as DataImportRule).dlgTargetFeatureClasses)
                    {
                        dlgTargetFeatureClassBases.Add(dlgTargetFeatureClass);
                    }
                }
                else if (dataImportRuleBase is DataMatchRule)
                {
                    foreach (DlgTargetMatchFeatureClass dlgTargetMatchFeatureClass in (dataImportRuleBase as DataMatchRule).dlgTargetMatchFeatureClass)
                    {
                        dlgTargetFeatureClassBases.Add(dlgTargetMatchFeatureClass);
                    }
                }
                else if (dataImportRuleBase is PipeImportRule)
                {
                    foreach (DlgTargetPipeFeatureClass dlgTargetPipeFeatureClass in (dataImportRuleBase as PipeImportRule).dlgTargetPipeFeatureClasses)
                    {
                        dlgTargetFeatureClassBases.Add(dlgTargetPipeFeatureClass);
                    }
                }
                else
                {
                    return false;
                }

                if (dlgTargetFeatureClassBases.Count == 0)
                {
                    LogHelper.WriteErrLog("建库方案中目标要素类列表为空，请检查！");
                    return false;
                }

                //目标的要素类序列
                FeatClsListTarget = new List<IFeatureClass>();
                SetProcessBarMax(dlgTargetFeatureClassBases.Count);
                //循环目标
                for (int i = 0; i < dlgTargetFeatureClassBases.Count; i++)
                {
                    SetProcessBarCurrent(i + 1);
                    pTargetFeatCls = CreateFeatureClass(dlgTargetFeatureClassBases[i], TargetWs, pTargetFeatDs, pSr, dlgTargetFeatureClassBases[i].HasM, dlgTargetFeatureClassBases[i].HasZ);
                    //目标数据不存在，需要写日志
                    if (pTargetFeatCls == null)
                    {
                        //LogHelper.WriteLog("目标要素类:[" + dlgTargetFeatureClass.FeatureClassName +
                        //                 dataImportRule.Affix + "]不存在，并且创建失败，请检查！");
                        //return false;
                    }
                    else
                    {
                        FeatClsListTarget.Add(pTargetFeatCls);
                    }
                }

                if (ConstructTargetFeatclsOver != null)//构造完目标要素类后要提示外界调用的类
                {
                    ConstructTargetFeatclsOver.Invoke(null, null);
                }
                LogHelper.WriteDoneLog("构造目标要素类成功。");
                return true;
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("构造目标要素类失败！" + e.Message + "\n");
                return false;
            }
        }

        #region Private functions

        /// <summary>
        /// 构造代码对应关系
        /// </summary>
        private bool ConstructFcodeRelation()
        {
            if (dataImportRule == null) return false;
            LogHelper.WriteLog("开始构造代码对应关系...");
            FcodeRelationPt = new Hashtable();
            FcodeRelationLn = new Hashtable();
            FcodeRelationPy = new Hashtable();
            FcodeRelationAnno = new Hashtable();
            Hashtable htTemp;
            //如果构造代码关系出现错误，还是继续构造完，把所有的问题都记录下来，这样就不用作业员改一个跑一遍程序再改一个再跑一遍程序了
            bool hasErr = false;
            try
            {                
                foreach (DlgTargetFeatureClass dlgTaregtFeatCls in dataImportRule.dlgTargetFeatureClasses)
                {
                    switch (dlgTaregtFeatCls.GeometryType)
                    {
                        case "点":
                            htTemp = FcodeRelationPt;
                            break;
                        case "线":
                            htTemp = FcodeRelationLn;
                            break;
                        case "面":
                            htTemp = FcodeRelationPy;
                            break;
                        case "注记":
                            htTemp = FcodeRelationAnno;
                            break;
                        default:
                            LogHelper.WriteErrLog("建库方案中[" + dlgTaregtFeatCls.FeatureClassAliasName + "]图层的要素几何类型[" + dlgTaregtFeatCls.GeometryType +
                                 "]系统无法识别，构造代码关系失败。目前几何类型仅支持：点、线、面、注记。");
                            hasErr = true;
                            continue;
                    }
                    foreach (FeatureCode featureCode in dlgTaregtFeatCls.featureCodes)
                    {
                        if (featureCode == null || string.IsNullOrWhiteSpace(featureCode.FCODE)) continue;                        
                        string target = featureCode.FCODE.Trim();
                        string source = string.IsNullOrWhiteSpace(featureCode.SOURCE) ? featureCode.FCODE.Trim() : featureCode.SOURCE.Trim();
                        if (string.IsNullOrWhiteSpace(source))//暂时支持空代码，因为有可能要创建一个空的库体，就没有任何要素
                            continue;
                        if (htTemp.ContainsKey(source.Trim()))
                        {
                            LogHelper.WriteErrLog("建库方案中[" + dlgTaregtFeatCls.FeatureClassAliasName.Trim() + "]图层中的源分类代码" + source +
                                (string.IsNullOrWhiteSpace(featureCode.FNAME) ? "" : "[" + featureCode.FNAME.Trim() + "]") +
                                 "在其它同几何类型的图层中已经存在。入库程序仅支持源代码与目标代码的一对一或者多对一的关系，不支持一对多的关系。");
                            hasErr = true;
                        }
                        else
                        {
                            htTemp.Add(source.Trim(), target.Trim());
                        }
                    }
                }
                if (hasErr) return false;
                LogHelper.WriteDoneLog("构造代码对应关系成功。\n");
                return true;
            }
            catch (Exception e)
            {
                LogHelper.WriteErrLog("构造代码对应关系失败！" + e.Message + "\n");
                return false;
            }
        }

        /// <summary>
        /// 获取目标数据集
        /// </summary>
        /// <param name="pFeatWs"></param>
        /// <param name="strFeatDsName"></param>
        /// <returns></returns>
        private IFeatureDataset GetTargetFeatDataset(IFeatureWorkspace pFeatWs, string strFeatDsName)
        {
            IFeatureDataset pFeatDs = null;
            try
            {
                pFeatDs = pFeatWs.OpenFeatureDataset(strFeatDsName);
            }
            catch (Exception e)
            {
               LogHelper.WriteErrLog("获取数据集失败：" + e.Message);
            }
            return pFeatDs;
        }

        /// <summary>
        /// 获取要素类
        /// </summary>
        /// <param name="pFeatClsContainer"></param>
        /// <param name="strFeatClsName"></param>
        /// <returns></returns>
        private IFeatureClass GetFeatCls(IFeatureClassContainer pFeatClsContainer, string strFeatClsName)
        {
            IFeatureClass pFeatCls = null;
            try
            {
                pFeatCls = pFeatClsContainer.get_ClassByName(strFeatClsName);
            }
            catch (Exception e)
            {
               LogHelper.WriteErrLog("获取要素类失败：" + e.Message);
            }
            return pFeatCls;
        }
        
        /// <summary>
        /// 构造数据导入键值
        /// </summary>
        /// <param name="pTargetFeatCls"></param>
        /// <param name="pSourceFeatCls"></param>
        /// <param name="dlgTargetFeatureClass"></param>
        /// <param name="ht"></param>
        /// <param name="htDefaultValue"></param>
        /// <param name="dlgDataConvertList"></param>
        /// <returns></returns>
        private bool ConstructDataImportKey(IFeatureClass pTargetFeatCls, IFeatureClass pSourceFeatCls, 
            DlgTargetFeatureClass dlgTargetFeatureClass, Hashtable fieldRelation, Hashtable fieldDefaultValue, List<DlgDataConvert> dlgDataConvertList)
        {
            bool needConstruct = false;
            switch (pTargetFeatCls.FeatureType)
            {
                case esriFeatureType.esriFTAnnotation: //当目标数据的要素类型为注记型，数据源也是注记或者CAD注记类型时，需要构造
                    if (pSourceFeatCls.FeatureType == esriFeatureType.esriFTAnnotation ||
                        pSourceFeatCls.FeatureType == esriFeatureType.esriFTCoverageAnnotation)
                        needConstruct = true;
                    break;
                case esriFeatureType.esriFTSimple:    //当目标数据的要素类型为简单要素型，数据源与目标数据的几何类型一致时，需要构造
                    if (pSourceFeatCls.FeatureType == esriFeatureType.esriFTSimple &&
                        pSourceFeatCls.ShapeType == pTargetFeatCls.ShapeType) needConstruct = true;
                    break;
                default://对于其它要素类型，暂不支持
                    return true;
            }
            if (!needConstruct) return true;//若不需要构造，直接返回
            DlgDataConvert dlgDataConvert = new DlgDataConvert();
            dlgDataConvert.TargetFeatCls = pTargetFeatCls;
            dlgDataConvert.SourceFeatCls = pSourceFeatCls;
            switch (dlgTargetFeatureClass.GeometryType)
            {
                case "点":
                    dlgDataConvert.FcodeRelation = FcodeRelationPt;
                    break;
                case "线":
                    dlgDataConvert.FcodeRelation = FcodeRelationLn;
                    break;
                case "面":
                    dlgDataConvert.FcodeRelation = FcodeRelationPy;
                    break;
                case "注记":
                    dlgDataConvert.FcodeRelation = FcodeRelationAnno;
                    break;
                default:
                    LogHelper.WriteErrLog("建库方案中[" + dlgTargetFeatureClass.FeatureClassAliasName + "]图层的要素几何类型[" + dlgTargetFeatureClass.GeometryType +
                         "]系统无法识别，构造代码关系失败。目前几何类型仅支持：点、线、面、注记。");
                    return false;
            }
            //数据源找不到入库依据的字段时，其它要素类继续入
            ISpatialFilter pSpatialFilter = GetSpatilFilter(pSourceFeatCls, SourceFieldName, dlgTargetFeatureClass);
            if (pSpatialFilter == null) return true;
            dlgDataConvert.SpatialFilter = pSpatialFilter;
            dlgDataConvert.FieldRelation = fieldRelation;
            dlgDataConvert.FieldDefaultValue = fieldDefaultValue;
            dlgDataConvert.SourceCodeName = SourceFieldName;
            dlgDataConvert.NeedDelete = NeedDelete;
            dlgDataConvert.SetProcessBarMax = SetProcessBarMax;
            dlgDataConvert.SetProcessBarCurrent = SetProcessBarCurrent;
            //这才是关键
            dlgDataConvertList.Add(dlgDataConvert);
            return true;
        }

        /// <summary>
        /// 获取空间过滤器
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="strFCodeName"></param>
        /// <param name="dlgTargetFeatureClass"></param>
        /// <returns></returns>
        private ISpatialFilter GetSpatilFilter(IFeatureClass pFeatCls, string strFCodeName, DlgTargetFeatureClass dlgTargetFeatureClass)
        {
            ISpatialFilter pSpatialFilter = new SpatialFilter();
            //如果是数据源注记类，并且注记的代码关系列表为空，则直接取所有要素；否则按照代码对应关系进行构造
            if (pFeatCls.FeatureType == esriFeatureType.esriFTCoverageAnnotation && FcodeRelationAnno.Count == 0 && dlgTargetFeatureClass.GeometryType == "注记")
            {
                pSpatialFilter.WhereClause = "Text is not null and Text <> ''";
            }
            else if (pFeatCls.FeatureType == esriFeatureType.esriFTAnnotation && FcodeRelationAnno.Count == 0 && dlgTargetFeatureClass.GeometryType == "注记")
            {
                pSpatialFilter.WhereClause = "TextString is not null and TextString <> ''";
            }
            else  //获取数据源要素类的所有要素，依次遍历
            {
                string strCode = "";
                IFields pFields = pFeatCls.Fields;
                int intField = pFields.FindField(strFCodeName.Trim());//首先判断搜索的字段是否存在
                if (intField < 0)
                {
                    pSpatialFilter = null;
                    return null;
                }
                List<FeatureCode> featureCodes = dlgTargetFeatureClass.featureCodes;
                if (featureCodes.Count > 0)
                {
                    for (int i = 0; i < featureCodes.Count; i++)
                    {
                        if (featureCodes[i] == null || featureCodes[i].FCODE == null) continue;
                        string temp = (featureCodes[i].SOURCE == null || featureCodes[i].SOURCE.Trim() == "") ?
                                    featureCodes[i].FCODE.Trim() : featureCodes[i].SOURCE.Trim();
                        if (pFields.get_Field(intField).Type == esriFieldType.esriFieldTypeString)
                        {
                            strCode = strCode + ",'" + temp + "'";
                        }
                        else
                        {
                            strCode = strCode + "," + temp;
                        }
                    }
                    if (strCode == "") return null;
                    strCode = strCode.Substring(1, strCode.Length - 1);
                }
                else//如果没有子节点的话则不入，但不置为空，否则null把所有数据都入了
                {
                    LogHelper.WriteErrLog("目标数据[" + dlgTargetFeatureClass.FeatureClassAliasName + "]的代码列表为空，请检查。");
                    return null;
                }
                strCode = strFCodeName + " in (" + strCode + ")";
                pSpatialFilter.WhereClause = strCode;
            }
            //属性查询过滤
            pSpatialFilter.SubFields = "*";
            try
            {
                if (pFeatCls.FeatureCount(pSpatialFilter) > 0)
                    return pSpatialFilter;
                else
                    return null;
            }
            catch (Exception e)
            {
                LogHelper.WriteErrLog("获取选择集失败：" + e.Message);
                return null;
            }
        }
        
        /// <summary>
        /// 根据prj文件和数据集名称创建数据集
        /// </summary>
        /// <param name="workspace"></param>
        /// <param name="dsName"></param>
        /// <returns></returns>
        private IFeatureDataset CreateFeatureDataset(IWorkspace workspace, string dsName)
        {
            if (string.IsNullOrWhiteSpace(dsName) || workspace == null || !(workspace is IFeatureWorkspace)) return null;
            IWorkspace2 pWs2 = workspace as IWorkspace2;
            IFeatureWorkspace pFeatWs = workspace as IFeatureWorkspace;
            IFeatureDataset pFeatDs = null;
            if (pWs2.get_NameExists(esriDatasetType.esriDTFeatureDataset, dsName))
            {
                pFeatDs = pFeatWs.OpenFeatureDataset(dsName);
            }
            else
            {
                LogHelper.WriteLog("数据集[" + dsName + "]不存在，系统将自动创建该数据集。");
                ISpatialReference pSpatialRef = GetSR();
                try
                {
                    pFeatDs = pFeatWs.CreateFeatureDataset(dsName, pSpatialRef);//创建数据集
                    LogHelper.WriteDoneLog("数据集[" + dsName + "]创建成功。\n");
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("数据集[" + dsName + "]创建失败！" + ex.Message + "\n");
                    return null;
                }
            }
            return pFeatDs;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ISpatialReference GetSR()
        {
            ISpatialReference pSpatialRef = GetSpatialReferenceFromPrj();
            if (pSpatialRef == null)
            {
               LogHelper.WriteErrLog("空间参考打开失败！");
                return null;
            }
            SetSpatialDomain(pSpatialRef);

            //还差选择Z坐标
            IVerticalCoordinateSystem pVerticalCoordinateSystem = GetVerticalCoordinateSystem();
            if (pVerticalCoordinateSystem != null)
            {
                (pSpatialRef as ISpatialReference3).VerticalCoordinateSystem = pVerticalCoordinateSystem;
            }


            return pSpatialRef;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private IVerticalCoordinateSystem GetVerticalCoordinateSystem()
        {
            OpenFileDialog openFileDialog1;
            openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Title = "请选择Z空间参考文件";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.Multiselect = false;
            openFileDialog1.Filter = "空间参考文件(*.prj)|*.prj";

            //added by sheng 让用户每次打开的时候，直接定位到保存坐标文件的目录
            openFileDialog1.InitialDirectory = AppConfig.CoordinatePath;
            openFileDialog1.FileName = "";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {

                StreamReader sr = File.OpenText(openFileDialog1.FileName);
                string srInfo = sr.ReadToEnd();
                ISpatialReferenceFactory3 pSpatRefFact = new SpatialReferenceEnvironmentClass();

                IVerticalCoordinateSystem pVerticalCoordinateSystem = pSpatRefFact.CreateVerticalCoordinateSystemFromESRISpatialReference(srInfo);
                return pVerticalCoordinateSystem;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获取空间参考
        /// </summary>
        /// <returns></returns>
        private ISpatialReference GetSpatialReferenceFromPrj()
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog(); 
            openFileDialog1.Title = "请选择XY空间参考文件";
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.Multiselect = false;
            openFileDialog1.Filter = "空间参考文件(*.prj)|*.prj";
            //added by sheng 让用户每次打开的时候，直接定位到保存坐标文件的目录
            openFileDialog1.InitialDirectory = AppConfig.CoordinatePath;
            openFileDialog1.FileName = "";
            ISpatialReference pSpatRef = new UnknownCoordinateSystemClass();
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if (openFileDialog1.FileName == "") return null;
                ISpatialReferenceFactory3 pSpatRefFact = new SpatialReferenceEnvironmentClass();
                pSpatRef = pSpatRefFact.CreateESRISpatialReferenceFromPRJFile(openFileDialog1.FileName);              
                if (pSpatRef == null)
                {
                    MsgHelper.ShowErrorMsgbox("没有找到投影信息或者投影文件已经破坏，请检查！");
                    return null;
                }
                return pSpatRef;
            }
            return pSpatRef;
        }

        /// <summary>
        /// 设置范围
        /// </summary>
        /// <param name="pSpatialRef"></param>
        private void SetSpatialDomain(ISpatialReference pSpatialRef)
        {
            FrmSetSpatialRef ssr = new FrmSetSpatialRef();
            ssr.SpatialFileName = AppConfig.ConfigPath + "\\spatialref.dat";
            if (ssr.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                pSpatialRef.SetDomain(ssr.Minx, ssr.Maxx, ssr.Miny, ssr.Maxy);
            }
            else
            {
                pSpatialRef.SetDomain(-5123200, 900714802274.099, -10002100, 900709923374.099);
            }
            pSpatialRef.SetMDomain(-100000, 900719825474.099);
            pSpatialRef.SetZDomain(-100000, 900719825474.099);
        }

        /// <summary>
        /// 创建数据集
        /// </summary>
        /// <param name="dlgTargetFeatureClassBase"></param>
        /// <param name="pFeatDs"></param>
        /// <param name="hasM"></param>
        /// <param name="hasZ"></param>
        /// <returns></returns>
        private IFeatureClass CreateFeatureClass(DlgTargetFeatureClassBase dlgTargetFeatureClassBase, IFeatureDataset pFeatDs, bool hasM, bool hasZ)
        {
            if (pFeatDs == null) return null;
            IFields pFields = new FieldsClass();
            IField pField = null;
            IFieldEdit pFieldEdit = null;
            IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;

            IWorkspace pWs = pFeatDs.Workspace;
            IWorkspace2 pWs2 = pWs as IWorkspace2;//IWorkspace2接口用来判断某要素类是否存在
            IFeatureWorkspace pFeatWS = pWs as IFeatureWorkspace;

            IFieldChecker pFieldChecker;
            pFieldChecker = new FieldCheckerClass();
            pFieldChecker.ValidateWorkspace = pWs;

            IFeatureClass pFeatCls;

            string affix = StringHelper.ConvertWRTNull(dataImportRuleBase.Affix);//后缀

            #region 判断要素类是否已经存在
            string fcName = dlgTargetFeatureClassBase.FeatureClassName.Trim() + affix;

            if (pWs2.get_NameExists(esriDatasetType.esriDTFeatureClass, fcName))
            {
                IFeatureClass pFeatClsSub;
                pFeatClsSub = pFeatWS.OpenFeatureClass(fcName);

                if (pFeatClsSub.FeatureDataset.Name == pFeatDs.Name)
                    return pFeatClsSub;
                #region 考虑目标要素类存在，但不在目标数据集中的情况
                else
                {
                    if (sameWay)
                    {
                        if (yesOrNo)
                        {
                            IDataset pDataset = pFeatClsSub as IDataset;

                            if (pDataset.CanDelete())
                            {
                                try
                                {
                                    pDataset.Delete();
                                }
                                catch
                                {
                                   LogHelper.WriteErrLog("要素类[" + fcName + "]删除失败，创建新要素类失败！");
                                    return null;
                                }
                            }
                        }
                        else
                        {
                           LogHelper.WriteErrLog("要素类[" + fcName + "]目前不能被删除，创建新要素类失败！");
                            return null;
                        }
                    }
                    else
                    {
                        
                        string msg ="目标要素类[" + fcName + 
                            "]已经存在，但是不在目标数据集中，是否需要删除原有要素类，并在目标数据集中创建一个新的要素类？";
                        FrmYesOrNoQuery query = new FrmYesOrNoQuery(msg);

                        if(query.ShowDialog()==DialogResult.Yes )
                        {
                            yesOrNo =true;
                            sameWay =query.SameWay ;
                            IDataset pDataset = pFeatClsSub as IDataset;
                        
                            if (pDataset.CanDelete())
                            {
                                try
                                {
                                    pDataset.Delete();
                                }
                                catch
                                {
                                   LogHelper.WriteErrLog("要素类[" + fcName + "]删除失败，创建新要素类失败！");
                                    return null;
                                }
                            }
                            else
                            {
                               LogHelper.WriteErrLog("要素类[" + fcName + "]目前不能被删除，创建新要素类失败！");
                                return null;
                            }
                        }
                        else
                        {
                            yesOrNo =false;
                            sameWay =query.SameWay ;
                            return null;
                        }
                    }
                }
                #endregion
            }
            #endregion

            #region 验证要素类名称是否符合规范
            string fixedName = "";
            pFieldChecker.ValidateTableName(fcName, out fixedName);
            if (fcName != fixedName)
            {
               LogHelper.WriteErrLog("目标要素类[" + fcName + "]的名称不符合规范，请重新设置！");
                return null;
            }
            #endregion

            #region 遍历属性字段,去掉重复的属性
            Hashtable ht = new Hashtable();
            for (int i = 0; i < dlgTargetFeatureClassBase.attrFields.Count; i++)
            {
                AttrField attrField = dlgTargetFeatureClassBase.attrFields[i] as AttrField;
                //去掉空格
                if (ht.ContainsKey(attrField.TargetFieldName.Trim()))
                {
                    dlgTargetFeatureClassBase.attrFields.Remove(dlgTargetFeatureClassBase.attrFields[i]);
                }
                else
                {
                    ht.Add(attrField.TargetFieldName.Trim(), attrField);
                }
            }
            ht = null;
            #endregion

            #region 创建建库方案定义的字段
            if (dlgTargetFeatureClassBase.attrFields.Count > 0)
            {
                for (int i = 0; i < dlgTargetFeatureClassBase.attrFields.Count; i++)
                {
                    AttrField attrField = dlgTargetFeatureClassBase.attrFields[i] as AttrField;
                    FieldInfoType pFieldInfo = new FieldInfoType();

                    //modified by sheng at 2013-07-04 如果是入库依据字段，则不能为空
                    pFieldInfo.isNullable = (attrField.TargetFieldName != SourceFieldName);// true; //都让它可以为空吧，否则入库会容易出错

                    //类型
                    pFieldInfo.fieldType = Convertor.GetFieldType(attrField.Type);
                    pFieldInfo.aliasName = attrField.Description.Trim();
                    pFieldInfo.fieldName = attrField.TargetFieldName.Trim();
                    if (!string.IsNullOrEmpty(attrField.length))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.length))
                            pFieldInfo.length = Convert.ToInt32(attrField.length);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[长度]类型不是数字型，请检查建库方案文件！");
                    }
                    if (!string.IsNullOrEmpty(attrField.precision))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.precision))
                            pFieldInfo.precision = Convert.ToInt32(attrField.precision);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[精度]类型不是数字型，请检查建库方案文件！");
                    }
                    if (!string.IsNullOrEmpty(attrField.scale))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.scale))
                            pFieldInfo.scale = Convert.ToInt32(attrField.scale);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[小数位数]类型不是数字型，请检查建库方案文件！");
                    }
                    //pFieldsEdit.set_Field(i+2, CreateField(pFieldInfo));
                    pField = CreateField(pFieldInfo);
                    if (pField != null) pFieldsEdit.AddField(pField);
                }

                #region 验证要各字段是否符合规范
                IFields validatedFields = null;
                IEnumFieldError enumFieldError = null;
                pFieldChecker.Validate(pFields, out enumFieldError, out validatedFields);

                // Display any errors that were found.  
                if (enumFieldError != null)
                {
                    IFieldError fieldError = null;
                    while ((fieldError = enumFieldError.Next()) != null)
                    {
                        // Get the field the error occurred on.      
                        IField errorField = pFields.get_Field(fieldError.FieldIndex);
                       LogHelper.WriteErrLog("创建目标数据[" + fcName + "]的字段[" + errorField.Name + "]时出错：" +
                            GetFieldErrInfo(fieldError.FieldError));
                    }
                    return null;
                }
                #endregion
            }
            #endregion

            if (dlgTargetFeatureClassBase.GeometryType == "注记")
            {
                #region 创建注记要素类
                try
                {
                    int annoScale = 500;

                    //if (SystemConfig.systemConfigXml.规则.注记比例尺 != null &&
                    //    StringUtility.CanConvert2Int(SystemConfig.systemConfigXml.规则.注记比例尺))
                    if (dataImportRuleBase != null && dataImportRuleBase.AnnoSacle != null &&
                        StringHelper.CanConvert2Int(dataImportRuleBase.AnnoSacle))
                    {
                        annoScale = Int32.Parse(dataImportRuleBase.AnnoSacle);
                    }

                    //pFeatCls = GeodatabaseHelper.CreateAnnotationFeatureClass((IWorkspace)pFeatWS, fcName, pFields, null, pFeatDs);
                    pFeatCls = GeodatabaseHelper.CreateAnnotationFeatureClass((IWorkspace)pFeatWS, fcName, pFields, annoScale);

                    //除了注记默认的字段外，如果规则中配置了其它字段，一并加进去
                    if (pFields.FieldCount > 0)
                    {
                        for (int i = 0; i < pFields.FieldCount; i++)
                        {
                            if (pFeatCls.Fields.FindField(pFields.get_Field(i).Name) == -1)
                                pFeatCls.AddField(pFields.get_Field(i));
                        }
                    }
                    LogHelper.WriteDoneLog("注记类:[" + fcName + "]创建成功。");
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("注记类:[" + fcName + "]创建失败，请检查表名是否规范。" + ex.Message);
                    return null;
                }
                #endregion
            }
            else
            {
                #region 创建简单要素类
                ////如果一开始不指定字段的个数，能成功么？试一试（已试。可以！）
                //pFieldsEdit.FieldCount_2 = 2 + dlgTargetFeatureClassBase.attrFields.Count;

                //如果不创建OID字段，能成功么？试一试（已试。没有OID可以创建要素类，但是不能创建要素）
                //创建OID字段
                pField = new FieldClass();
                pFieldEdit = pField as IFieldEdit;
                pFieldEdit.Name_2 = "OBJECTID";
                pFieldEdit.AliasName_2 = "OID";
                pFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
                //pFieldsEdit.set_Field(0, pFieldEdit);
                pFieldsEdit.AddField(pFieldEdit);

                //Geomtry定义
                IGeometryDef pGeomDef = new GeometryDefClass();
                IGeometryDefEdit pGeomDefEdit = pGeomDef as IGeometryDefEdit;
                pGeomDefEdit.GeometryType_2 = Convertor.GetGeometryType(dlgTargetFeatureClassBase.GeometryType.ToString());

                IGeoDataset pGeoDataset = pFeatDs as IGeoDataset;

                pGeomDefEdit.SpatialReference_2 = pGeoDataset.SpatialReference;

                pGeomDefEdit.HasM_2 = hasM;
                pGeomDefEdit.HasZ_2 = hasZ;

                //创建Shape字段
                pField = new FieldClass();
                pFieldEdit = pField as IFieldEdit;
                pFieldEdit.Name_2 = "Shape";
                pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
                pFieldEdit.GeometryDef_2 = pGeomDefEdit;
                pFieldEdit.IsNullable_2 = true;
                pFieldEdit.Required_2 = true;
                //pFieldsEdit.set_Field(1, pFieldEdit);
                pFieldsEdit.AddField(pFieldEdit);

                try
                {
                    pFeatCls = pFeatDs.CreateFeatureClass(fcName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
                    LogHelper.WriteDoneLog("要素类:[" + fcName + "]创建成功。");
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("要素类:[" + fcName + "]创建失败：" + ex.Message);
                    return null;
                }

                #endregion
            }

            #region 给要素类赋别名

            if (pFeatCls == null) return null;

            try
            {

                IClassSchemaEdit pClassSchemaEdit = pFeatCls as IClassSchemaEdit;
                pClassSchemaEdit.AlterAliasName(dlgTargetFeatureClassBase.FeatureClassAliasName.Trim());
            }
            catch (Exception ex)
            {
               LogHelper.WriteErrLog("给目标要素类[" + fcName + "]赋别名时出错：" + ex.Message);
            }
            #endregion

            return pFeatCls;
        }

        /// <summary>
        /// 创建数据集
        /// </summary>
        /// <param name="dlgTargetFeatureClassBase"></param>
        /// <param name="pFeatWs"></param>
        /// <param name="pFeatDs"></param>
        /// <param name="pSr"></param>
        /// <param name="hasM"></param>
        /// <param name="hasZ"></param>
        /// <returns></returns>
        private IFeatureClass CreateFeatureClass(DlgTargetFeatureClassBase dlgTargetFeatureClassBase, IWorkspace pWs, IFeatureDataset pFeatDs,ISpatialReference pSr, bool hasM, bool hasZ)
        {
            IFields pFields = new FieldsClass();
            IField pField = null;
            IFieldEdit pFieldEdit = null;
            IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;

            IWorkspace2 pWs2 = pWs as IWorkspace2;//IWorkspace2接口用来判断某要素类是否存在
            IFeatureWorkspace pFeatWS = pWs as IFeatureWorkspace;

            IFieldChecker pFieldChecker;
            pFieldChecker = new FieldCheckerClass();
            pFieldChecker.ValidateWorkspace = pWs;

            IFeatureClass pFeatCls;

            string affix = StringHelper.ConvertWRTNull(dataImportRuleBase.Affix);//后缀

            #region 判断要素类是否已经存在
            string fcName = dlgTargetFeatureClassBase.FeatureClassName.Trim() + affix;

            if (pWs2.get_NameExists(esriDatasetType.esriDTFeatureClass, fcName))
            {
                IFeatureClass pFeatClsSub = pFeatWS.OpenFeatureClass(fcName);
                //added by sheng at 2013-06-18 如果找到同名的就直接返回算了
                return pFeatClsSub;

            }
            #endregion

            #region 验证要素类名称是否符合规范
            string fixedName = "";
            pFieldChecker.ValidateTableName(fcName, out fixedName);
            if (fcName != fixedName)
            {
               LogHelper.WriteErrLog("目标要素类[" + fcName + "]的名称不符合规范，请重新设置！");
                return null;
            }
            #endregion

            #region 遍历属性字段,去掉重复的属性
            Hashtable ht = new Hashtable();
            for (int i = 0; i < dlgTargetFeatureClassBase.attrFields.Count; i++)
            {
                AttrField attrField = dlgTargetFeatureClassBase.attrFields[i] as AttrField;
                //去掉空格
                if (ht.ContainsKey(attrField.TargetFieldName.Trim()))
                {
                    dlgTargetFeatureClassBase.attrFields.Remove(dlgTargetFeatureClassBase.attrFields[i]);
                }
                else
                {
                    ht.Add(attrField.TargetFieldName.Trim(), attrField);
                }
            }
            ht = null;
            #endregion

            #region 创建建库方案定义的字段
            if (dlgTargetFeatureClassBase.attrFields.Count > 0)
            {
                for (int i = 0; i < dlgTargetFeatureClassBase.attrFields.Count; i++)
                {
                    AttrField attrField = dlgTargetFeatureClassBase.attrFields[i] as AttrField;
                    FieldInfoType pFieldInfo = new FieldInfoType();
                    
                    //modified by sheng at 2013-07-04 如果是入库依据字段，则不能为空
                    pFieldInfo.isNullable = (attrField.TargetFieldName != SourceFieldName);// true; //都让它可以为空吧，否则入库会容易出错

                    //类型
                    pFieldInfo.fieldType = Convertor.GetFieldType(attrField.Type);
                    pFieldInfo.aliasName = (attrField.Description == null) ? attrField.TargetFieldName : attrField.Description.Trim();
                    pFieldInfo.fieldName = attrField.TargetFieldName.Trim();
                    if (!string.IsNullOrEmpty(attrField.length))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.length))
                            pFieldInfo.length = Convert.ToInt32(attrField.length);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[长度]类型不是数字型，请检查建库方案文件！");
                    }
                    if (!string.IsNullOrEmpty(attrField.precision))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.precision))
                            pFieldInfo.precision = Convert.ToInt32(attrField.precision);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[精度]类型不是数字型，请检查建库方案文件！");
                    }
                    if (!string.IsNullOrEmpty(attrField.scale))
                    {
                        if (StringHelper.CanConvert2PositiveInt(attrField.scale))
                            pFieldInfo.scale = Convert.ToInt32(attrField.scale);
                        else
                            LogHelper.WriteErrLog("[" + pFieldInfo.fieldName + "]字段的[小数位数]类型不是数字型，请检查建库方案文件！");
                    }
                    //pFieldsEdit.set_Field(i+2, CreateField(pFieldInfo));
                    pField = CreateField(pFieldInfo); 
                    if (pField != null) pFieldsEdit.AddField(pField);
                }

                #region 验证要各字段是否符合规范
                IFields validatedFields = null;
                IEnumFieldError enumFieldError = null;
                pFieldChecker.Validate(pFields, out enumFieldError, out validatedFields);

                // Display any errors that were found.  
                if (enumFieldError != null)
                {
                    IFieldError fieldError = null;
                    while ((fieldError = enumFieldError.Next()) != null)
                    {
                        // Get the field the error occurred on.      
                        IField errorField = pFields.get_Field(fieldError.FieldIndex);
                       LogHelper.WriteErrLog("创建目标数据[" + fcName + "]的字段[" + errorField.Name + "]时出错：" +
                            GetFieldErrInfo(fieldError.FieldError));
                    }
                    return null;
                }
                #endregion
            }
            #endregion

            if (dlgTargetFeatureClassBase.GeometryType == "注记")
            {
                #region 创建注记要素类
                try
                {
                    int annoScale = 500;
                    if (dataImportRuleBase != null && dataImportRuleBase.AnnoSacle != null &&
                        StringHelper.CanConvert2Int(dataImportRuleBase.AnnoSacle))
                    {
                        annoScale = Int32.Parse(dataImportRuleBase.AnnoSacle);
                    }
                    pFeatCls = GeodatabaseHelper.CreateAnnotationFeatureClass((IWorkspace)pFeatWS, fcName, pFields, null, pFeatDs);

                    LogHelper.WriteDoneLog("注记类:[" + fcName + "]创建成功。");
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("注记类:[" + fcName + "]创建失败，请检查表名是否规范。" + ex.Message);
                    return null;
                }
                #endregion
            }
            else
            {
                #region 创建简单要素类
                ////如果一开始不指定字段的个数，能成功么？试一试（已试。可以！）
                //pFieldsEdit.FieldCount_2 = 2 + dlgTargetFeatureClassBase.attrFields.Count;

                //如果不创建OID字段，能成功么？试一试（已试。没有OID可以创建要素类，但是不能创建要素）
                //创建OID字段
                pField = new FieldClass();
                pFieldEdit = pField as IFieldEdit;
                pFieldEdit.Name_2 = "OBJECTID";
                pFieldEdit.AliasName_2 = "OID";
                pFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
                //pFieldsEdit.set_Field(0, pFieldEdit);
                pFieldsEdit.AddField(pFieldEdit);

                //Geomtry定义
                IGeometryDef pGeomDef = new GeometryDefClass();
                IGeometryDefEdit pGeomDefEdit = pGeomDef as IGeometryDefEdit;
                pGeomDefEdit.GeometryType_2 = Convertor.GetGeometryType(dlgTargetFeatureClassBase.GeometryType.ToString());

                //IGeoDataset pGeoDataset = pFeatDs as IGeoDataset;

                pGeomDefEdit.SpatialReference_2 = pSr;

                pGeomDefEdit.HasM_2 = hasM;
                pGeomDefEdit.HasZ_2 = hasZ;

                //创建Shape字段
                pField = new FieldClass();
                pFieldEdit = pField as IFieldEdit;
                pFieldEdit.Name_2 = "Shape";
                pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
                pFieldEdit.GeometryDef_2 = pGeomDefEdit;
                pFieldEdit.IsNullable_2 = true;
                pFieldEdit.Required_2 = true;
                //pFieldsEdit.set_Field(1, pFieldEdit);
                pFieldsEdit.AddField(pFieldEdit);

                try
                {
                    if (pFeatDs != null)
                    {
                        pFeatCls = pFeatDs.CreateFeatureClass(fcName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
                    }
                    else
                    {
                        pFeatCls = pFeatWS.CreateFeatureClass(fcName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");
                    }
                    LogHelper.WriteDoneLog("要素类:[" + fcName + "]创建成功。");
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("要素类:[" + fcName + "]创建失败：" + ex.Message);
                    return null;
                }

                #endregion
            }

            #region 给要素类赋别名

            if (pFeatCls == null) return null;

            try
            {

                IClassSchemaEdit pClassSchemaEdit = pFeatCls as IClassSchemaEdit;
                pClassSchemaEdit.AlterAliasName(dlgTargetFeatureClassBase.FeatureClassAliasName.Trim());
            }
            catch (Exception ex)
            {
               LogHelper.WriteErrLog("给目标要素类[" + fcName + "]赋别名时出错：" + ex.Message);
            }
            #endregion

            return pFeatCls;
        }
        
        /// <summary>
        /// 根据传入的esriFieldNameErrorType返回用户易懂的提示信息
        /// </summary>
        /// <param name="fieldNameErrorType"></param>
        /// <returns></returns>
        private string GetFieldErrInfo(esriFieldNameErrorType fieldNameErrorType)
        {
            string info = "";
            switch (fieldNameErrorType)
            {
                case esriFieldNameErrorType.esriNoFieldError:
                    info = "无该字段";
                    break;

                case esriFieldNameErrorType.esriSQLReservedWord:
                    info = "字段为SQL关键字";
                    break;

                case esriFieldNameErrorType.esriDuplicatedFieldName:
                    info = "字段重复";
                    break;

                case esriFieldNameErrorType.esriInvalidCharacter:
                    info = "字段中包含无效字符";
                    break;

                case esriFieldNameErrorType.esriInvalidFieldNameLength:
                    info = "字段太长";
                    break;

                default:
                    info = "未知错误";
                    break;
            }
            return info;
        }

        /// <summary>
        /// 创建字段
        /// </summary>
        /// <param name="pField"></param>
        /// <param name="pFieldEdit"></param>
        /// <param name="pFieldsEdit"></param>
        /// <param name="pFieldInfo"></param>
        /// <param name="index"></param>
        private IField CreateField(FieldInfoType pFieldInfo)
        {
            IField pField;
            pField = new FieldClass();

            IFieldEdit pFieldEdit;
            pFieldEdit = pField as IFieldEdit;

            pFieldEdit.IsNullable_2 = pFieldInfo.isNullable;
            pFieldEdit.Editable_2 = true;
            pFieldEdit.Name_2 = pFieldInfo.fieldName;
            pFieldEdit.AliasName_2 = pFieldInfo.aliasName;
            pFieldEdit.Type_2 = pFieldInfo.fieldType;

            //根据字段类型判断该pField字段的属性信息
            switch (pFieldInfo.fieldType)
            {
                case esriFieldType.esriFieldTypeSmallInteger:
                case esriFieldType.esriFieldTypeInteger:

                    //如果传进来的结构体信息没有precision则给一个默认值10
                    if (pFieldInfo.precision == 0)
                    {
                        pFieldEdit.Precision_2 = 10;
                    }
                    else
                    {
                        pFieldEdit.Precision_2 = pFieldInfo.precision;
                    }
                    break;
                case esriFieldType.esriFieldTypeSingle:
                case esriFieldType.esriFieldTypeDouble:
                    //如果传进来的结构体信息没有precision则给一个默认值38，Scale给8
                    if (pFieldInfo.precision == 0 || pFieldInfo.scale == 0)
                    {
                        pFieldEdit.Precision_2 = 38;
                        pFieldEdit.Scale_2 = 8;
                    }
                    else
                    {
                        pFieldEdit.Precision_2 = pFieldInfo.precision;
                        pFieldEdit.Scale_2 = pFieldInfo.scale;
                    }
                    break;
                case esriFieldType.esriFieldTypeString:
                    if (pFieldInfo.length == 0)
                    {
                        pFieldEdit.Length_2 = 255;
                    }
                    else
                    {
                        pFieldEdit.Length_2 = pFieldInfo.length;
                    }
                    break;
            }
            return pField;
        }

        #endregion
    }
}
